package com.ruoyi.cms.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.cms.entity.domain.Model;
import com.ruoyi.cms.entity.domain.ModelFavorite;
import com.ruoyi.cms.entity.req.MyFavoriteListReq;
import com.ruoyi.cms.entity.resp.ModelListResp;
import com.ruoyi.cms.mapper.ModelMapper;
import com.ruoyi.cms.service.ModelService;
import com.ruoyi.common.context.AppUserContext;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.RedisKeyEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.cms.mapper.ModelFavoriteMapper;
import com.ruoyi.cms.service.ModelFavoriteService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 模型收藏Service业务层处理
 */
@Service
@Slf4j
public class ModelFavoriteServiceImpl implements ModelFavoriteService {

    @Autowired
    private ModelFavoriteMapper modelFavoriteMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ModelService modelService;
    @Autowired
    private ModelMapper modelMapper;

    /**
     * 收藏
     */
    @Override
    @Transactional
    public R<Integer> favorite(Long modelId) {
        Long userId = AppUserContext.getUser().getUserId();

        Set<Long> favoriteSet = getFavoriteList();

        if (favoriteSet.contains(modelId)) {
            return R.ok(1, "您已收藏过");
        }

        ModelFavorite modelFavorite = new ModelFavorite();
        modelFavorite.setModelId(modelId);
        modelFavorite.setUserId(userId);
        modelFavorite.setCreateTime(new Date());
        modelFavorite.setUpdateTime(new Date());
        modelFavoriteMapper.insert(modelFavorite);

        modelMapper.addFavoriteNum(modelId);

        redisCache.setCacheSet(RedisKeyEnum.CMS_MODEL_FAVORITE_USER.getPrefix() + userId, Collections.singleton(modelId));

        long incr = redisCache.incr(RedisKeyEnum.CMS_MODEL_FAVORITE_COUNT.getPrefix() + modelId, 1);
        if (incr == 1L) {
            redisCache.expire(RedisKeyEnum.CMS_MODEL_FAVORITE_COUNT.getPrefix() + modelId, RedisKeyEnum.CMS_MODEL_FAVORITE_COUNT.getTimeout(),
                    RedisKeyEnum.CMS_MODEL_FAVORITE_COUNT.getTimeUnit());
        }

        return R.ok(1);
    }

    /**
     * 取消收藏
     */
    @Override
    @Transactional
    public R<Integer> cancelFavorite(Long modelId) {
        Long userId = AppUserContext.getUser().getUserId();

        Set<Long> favoriteSet = getFavoriteList();

        if (!favoriteSet.contains(modelId)) {
            return R.ok(0, "您未收藏过");
        }

        LambdaQueryWrapper<ModelFavorite> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ModelFavorite::getModelId, modelId);
        queryWrapper.eq(ModelFavorite::getUserId, userId);
        modelFavoriteMapper.delete(queryWrapper);

        modelMapper.subtractFavoriteNum(modelId);

        redisCache.deleteCacheSet(RedisKeyEnum.CMS_MODEL_FAVORITE_USER.getPrefix() + userId, modelId);

        redisCache.incr(RedisKeyEnum.CMS_MODEL_FAVORITE_COUNT.getPrefix() + modelId, -1);

        return R.ok();
    }

    /**
     * 获取收藏列表
     */
    @Override
    public Set<Long> getFavoriteList() {
        Long userId = AppUserContext.getUser().getUserId();

        Set<Long> favoriteSet = redisCache.getCacheSet(RedisKeyEnum.CMS_MODEL_FAVORITE_USER.getPrefix() + userId);

        if (CollUtil.isEmpty(favoriteSet)) {
            LambdaQueryWrapper<ModelFavorite> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ModelFavorite::getUserId, userId);
            List<ModelFavorite> modelFavorites = modelFavoriteMapper.selectList(queryWrapper);

            favoriteSet = CollUtil.emptyIfNull(modelFavorites).stream().map(ModelFavorite::getModelId).collect(Collectors.toSet());

            if (CollUtil.isEmpty(favoriteSet)) {
                favoriteSet.add(-1L);
            }

            redisCache.setCacheSet(RedisKeyEnum.CMS_MODEL_FAVORITE_USER.getPrefix() + userId, favoriteSet);
            redisCache.expire(RedisKeyEnum.CMS_MODEL_FAVORITE_USER.getPrefix() + userId, RedisKeyEnum.CMS_MODEL_FAVORITE_USER.getTimeout(),
                    RedisKeyEnum.CMS_MODEL_FAVORITE_USER.getTimeUnit());
        }

        return favoriteSet;
    }

    @Override
    public R<Page<ModelListResp>> myFavoriteList(MyFavoriteListReq req) {
        Long userId = AppUserContext.getUser().getUserId();
        req.setUserId(userId);

        Page<Model> page = new Page<>(req.getCurrent(), req.getSize());

        page = modelFavoriteMapper.selectFavoriteList(req, page);

        Page<ModelListResp> modelListRespPage = (Page<ModelListResp>) page.convert(model -> {
            ModelListResp modelListResp = new ModelListResp();
            ModelListResp.ModelDetail modelDetail = modelListResp.getModelDetail();

            modelDetail.setId(model.getId());
            modelDetail.setName(model.getName());
            modelDetail.setCoverPhotoUrl(model.getCoverPhotoUrl());
            modelDetail.setCreator(model.getCreator());
            modelDetail.setLikeNum(model.getLikeNum());
            modelDetail.setCreateTime(model.getCreateTime());

            modelListResp.setModelAuthorInfo(modelService.convertAuthorInfo(model.getCreator()));

            return modelListResp;
        });

        return R.ok(modelListRespPage);
    }

}
